package com.youyou.utils;

import com.youyou.annotation.FieldCompare;
import com.youyou.entity.FieldDiffent;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author:Lau
 * @create: 2023-03-30 11:00
 * @Description: 对比对象属性差异工具类
 */
public class FieldCompareUtil {

    public static <T> List<FieldDiffent> compare(Class<T> type, T newObject, T oldObject) throws Exception {
        // 变更的记录列表
        List<FieldDiffent> changeLogFields = new ArrayList<>();

        Class<?> newObj = newObject.getClass();
        Field[] newFields = type.getDeclaredFields();
        for (int i = 0; i < newFields.length; i++) {
            FieldCompare newAnnotation = newFields[i].getAnnotation(FieldCompare.class);
            if (null != newAnnotation) {
                String fieldName = newFields[i].getName();
                PropertyDescriptor newPd = new PropertyDescriptor(fieldName, newObj);
                Method getMethodNew = newPd.getReadMethod();
                Object oldVal = getMethodNew.invoke(oldObject);
                Object newVal = getMethodNew.invoke(newObject);
                boolean eq = false;
                if (oldVal instanceof String) {
                    String s1 = String.valueOf(oldVal).trim();
                    String s2 = String.valueOf(newVal).trim();
                    eq = !s1.equals(s2);
                } else if (oldVal instanceof Integer) {
                    int i1 = (Integer) oldVal;
                    int i2 = (Integer) newVal;
                    eq = i1 != i2;
                } else if (oldVal instanceof Double) {
                    double d1 = (Double) oldVal;
                    double d2 = (Double) newVal;
                    eq = d1 != d2;
                } else if (oldVal instanceof BigDecimal) {
                    BigDecimal b1 = (BigDecimal) oldVal;
                    BigDecimal b2 = (BigDecimal) newVal;
                    eq = b1.compareTo(b2) != 0;
                } else if (oldVal instanceof Long) {
                    long l1 = (Long) oldVal;
                    long l2 = (Long) newVal;
                    eq = l1 != l2;
                } else {
                    eq = !oldVal.equals(newVal);
                }
                String s1 = oldVal == null ? "" : oldVal.toString().trim();
                String s2 = newVal == null ? "" : newVal.toString().trim();
                if (eq) {
                    Map<String, String> map = codeToNameMap(newAnnotation);
                    if (map.size() > 0) {
                        changeLogFields.add(new FieldDiffent(newAnnotation.chineseName(),fieldName, map.get(s1), map.get(s2)));
                    } else {
                        changeLogFields.add(new FieldDiffent(newAnnotation.chineseName(),fieldName, s1, s2));
                    }
                }
            }
        }
        return changeLogFields;
    }

    /**
     * 字典映射 使用方式:
     * @param newAnnotation
     * @return
     */
    private static Map<String, String> codeToNameMap(FieldCompare newAnnotation) {
        Map<String, String> map = new HashMap<>();
        String properties = newAnnotation.properties();
        if (properties != null && properties.length() > 0) {
            String[] propertiesArr = properties.split(",");
            for (String propertie : propertiesArr) {
                String[] split = propertie.split(":");
                map.put(split[0], split[1]);
            }
        }
        return map;
    }
}

